<!--
    组件名称：表格转图表
    属性：表头、表格数据
    输出： clickChart方法： 点击图表事件，传出点击的图表的item
-->
<template>
  <!--图表渲染区-->
  <div class="chart-main" v-if="data.echartsList.length">
    <div v-for="(item, index) in data.echartsList" :key="index" class="chart-render-box">
      <div class="operation">
        <el-icon @click="onEdit(item)"><Edit /></el-icon>
        <el-icon @click="onDelete(index)"><CircleCloseFilled /></el-icon>
      </div>
      <div class="table-chart-render"></div>
    </div>
  </div>

  <!--图表配置弹窗-->
  <el-dialog
    v-model="showDialog"
    :title="(data.chartId && '编辑图表') || '新建图表'"
    width="80vw"
    destroy-on-close
    @close="onClose"
  >
    <div class="dialog-content">
      <div class="left">
        <div class="item-form">
          <el-divider content-position="left">选择表格中要生成图表的列</el-divider>
          <el-form size="small" label-width="100">
            <el-form-item>
              <template #label>
                <el-tooltip
                  effect="dark"
                  content="为饼图时，只会将选择的首条数据转为饼图"
                  placement="top"
                >
                  <span>
                    选择列
                    <el-icon><WarningFilled /></el-icon>
                  </span>
                </el-tooltip>
              </template>
              <template #default>
                <el-select
                  multiple
                  v-model="data.chartForm.pickColumn"
                  placeholder="请选择"
                  @change="onChange"
                >
                  <el-option
                    v-for="item in columns"
                    :key="item.key"
                    :value="item.prop + '$' + item.label"
                    :label="item.label"
                  />
                </el-select>
              </template>
            </el-form-item>
            <el-form-item label="图表标题">
              <el-input
                v-model="data.chartForm.title"
                placeholder="请输入"
                :disabled="!data.chartForm.pickColumn.length"
                clearable
              />
            </el-form-item>
          </el-form>
        </div>
        <div class="item-form">
          <el-divider content-position="left">图表布局</el-divider>
          <div class="chart-type">
            <el-radio-group
              v-model="data.chartForm.chartType"
              size="small"
              :disabled="!data.chartForm.pickColumn.length"
            >
              <el-radio-button label="柱状图" value="bar" />
              <el-radio-button label="折线图" value="line" />
              <el-radio-button label="饼状图" value="pie" />
            </el-radio-group>
          </div>
          <el-form size="small" label-width="100" inline>
            <template v-for="(item, index) in FORMLIST[data.chartForm.chartType]" :key="item.prop">
              <div class="col-item" v-if="index < 6">
                <el-form-item :label="item.label">
                  <component
                    :is="item.tag"
                    :style="item.style"
                    :disabled="!data.chartForm.pickColumn.length"
                    v-model="data.chartForm[item.prop]"
                    v-bind="item.attr"
                  >
                    <template v-if="item.tag === 'el-select'">
                      <el-option
                        v-for="value in OPTIONS[item.prop]"
                        :key="value.value"
                        :value="value.value"
                        :label="value.label"
                      />
                    </template>
                  </component>
                </el-form-item>
              </div>
            </template>
            <el-form-item v-if="FORMLIST[data.chartForm.chartType].length > 6" label=" ">
              <el-button
                type="primary"
                :disabled="!data.chartForm.pickColumn.length"
                @click="data.showMoreDialog = true"
              >
                更多设置
              </el-button>
            </el-form-item>
          </el-form>
        </div>
      </div>
      <div class="right">
        <div id="previewChart" class="chart-box"></div>
      </div>
    </div>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="onClose">取消</el-button>
        <el-button type="primary" :disabled="!data.chartForm.pickColumn.length" @click="onConfirm">
          确认
        </el-button>
      </div>
    </template>
  </el-dialog>
  <el-dialog v-model="data.showMoreDialog" width="50vw" destroy-on-close draggable>
    <el-form label-width="100">
      <template v-for="(item, index) in FORMLIST[data.chartForm.chartType]" :key="item.prop">
        <el-form-item v-if="index > 5" :label="item.label">
          <component
            :is="item.tag"
            :style="item.style"
            :disabled="!data.chartForm.pickColumn.length"
            v-model="data.chartForm[item.prop]"
            v-bind="item.attr"
          >
            <template v-if="item.tag === 'el-select'">
              <el-option
                v-for="value in OPTIONS[item.prop]"
                :key="value.value"
                :value="value.value"
                :label="value.label"
              />
            </template>
          </component>
        </el-form-item>
      </template>
    </el-form>
  </el-dialog>
</template>

<script setup>
import * as echarts from 'echarts';
import { FORMLIST, OPTIONS } from '../constant/echarts';
import { useEcharts } from '../hooks';

const showDialog = defineModel('showDialog'); //弹窗显隐
const { columns, tableData } = defineProps({
  //表格的列
  columns: {
    type: Array,
    default: () => [],
  },
  //表格数据
  tableData: {
    type: Array,
    default: () => [],
  },
});

const data = reactive({
  showMoreDialog: false, //更多设置弹窗
  chartId: '', //图表id
  echartsList: [], //图表列表
  chartData: [], //echarts数据
  chartOption: {}, //echarts的配置
  //配置表单
  chartForm: {
    chartType: 'bar',
    pickColumn: [],
    labelPosition: '',
    legendPosition: '',
    legendSize: '25-14',
    opacity: 0,
    pieSize: 50,
    ringSize: 10,
    xAxisData: [],
    leftSpace: '5%',
    rightSpace: '5%',
    bottomSpace: '8%',
    color: [],
  },
});

//监听配置的变化
watch(
  () => data.chartForm,
  (newVal) => {
    if (showDialog.value && data.chartForm.pickColumn.length) {
      const fn = {
        bar: useEcharts.rawBar,
        line: useEcharts.rawLine,
        pie: useEcharts.rawPie,
      };

      if (newVal.chartType === 'pie') {
        //组装饼图数据
        const pieData = Object.entries(data.chartData[0].value).map((item) => {
          return {
            name: item[0],
            value: item[1],
          };
        });
        data.chartOption = fn[newVal.chartType](pieData, data.chartForm);
      } else {
        data.chartOption = fn[newVal.chartType](data.chartData, data.chartForm);
      }
    } else {
      echarts.init(document.getElementById('previewChart')).clear();
    }
  },
  {
    deep: true,
  },
);

onMounted(() => {
  init();
});

/**
 * 初始化
 * */
const init = () => {
  data.echartsList = JSON.parse(localStorage.getItem('echartsList')) || [];

  nextTick(() => {
    if (data.echartsList.length) {
      data.echartsList.map((item, index) => {
        const el = document.getElementsByClassName('table-chart-render')[index];
        const myChart = echarts.init(el);
        myChart.clear();
        myChart.setOption(item.option);

        myChart.off('click', clickChart); //防止重复绑定事件
        myChart.on('click', clickChart); //绑定事件
      });
    }
  });
};
/**
 * 点击图表
 * @params {object} 点击的图表的item
 * */
const clickChart = (params) => {
  emit('clickChart', params);
};
/**
 * 选择列
 * @list {array} 选中的值
 * */
const onChange = (list) => {
  data.chartData = [];
  list.map((val) => {
    const obj = {};
    const arr = val.split('$'); //以连接符为基点切割
    tableData.map((item) => {
      obj[item[arr[0]]] ? obj[item[arr[0]]]++ : (obj[item[arr[0]]] = 1); //obj = {已处理:1}
    });
    data.chartData.push({ key: arr[1], value: obj });
  });

  //设置x轴坐标数据
  data.chartForm.pickColumn.length &&
    (data.chartForm.xAxisData = Object.keys(data.chartData[0].value));
  // if (data.chartForm.pickColumn.length) {
  //   !data.chartForm.xAxisData.length &&
  //     (data.chartForm.xAxisData = Object.keys(data.chartData[0].value)); //不再改变已设置的x轴坐标数据
  // } else {
  //   data.chartForm.xAxisData = [];
  // }
};
/**
 * 编辑图表
 * @item {object} 要编辑的图表的数据
 * */
const onEdit = (item) => {
  showDialog.value = true;
  const temp = JSON.parse(JSON.stringify(item));
  nextTick(() => {
    data.chartId = temp.id;
    data.chartOption = temp.option;
    data.chartData = temp.data;
    data.chartForm = temp.form;
  });
};
/**
 * 删除图表
 * @index {number} 要删除的图表的下标
 * */
const onDelete = (index) => {
  data.echartsList.splice(index, 1);
  localStorage.setItem('echartsList', JSON.stringify(data.echartsList));
  init();
};
/**
 * 关闭
 * */
const onClose = () => {
  showDialog.value = false;
  data.chartId = '';
  data.chartForm = {
    chartType: 'bar',
    pickColumn: [],
    labelPosition: '',
    legendPosition: '',
    legendSize: '25-14',
    opacity: 0,
    pieSize: 50,
    ringSize: 10,
    xAxisData: [],
    leftSpace: '5%',
    rightSpace: '5%',
    bottomSpace: '8%',
    color: [],
  };
};
/**
 * 确认
 * */
const onConfirm = () => {
  const chartData = {
    id: data.chartId,
    form: data.chartForm,
    data: data.chartData,
    option: data.chartOption,
  };

  if (chartData.id) {
    //编辑
    for (let i in data.echartsList) {
      //找到要替换的数据
      let item = data.echartsList[i];
      if (item.id === chartData.id) {
        item.form = chartData.form;
        item.data = chartData.data;
        item.option = chartData.option;
        break;
      }
    }
  } else {
    //新建
    chartData.id = Math.random().toString(36).substring(2, 10); //生成八位数ID
    data.echartsList.push(chartData);
  }
  localStorage.setItem('echartsList', JSON.stringify(data.echartsList));
  init();
  onClose();
};
const emit = defineEmits(['clickChart']);
</script>

<style scoped lang="less">
.chart-main {
  display: flex;
  flex-wrap: wrap;
  .chart-render-box {
    position: relative;
    width: 25%;
    min-height: 300px;
    .operation {
      display: none;
      position: absolute;
      z-index: 1;
      right: 0;
      cursor: pointer;
      .el-icon:hover {
        color: var(--el-color-primary);
      }
      .el-icon + .el-icon:hover {
        color: var(--el-color-danger);
      }
    }
    &:hover .operation {
      display: block;
    }
    .table-chart-render {
      width: 100%;
      height: 100%;
    }
    .operation .el-icon {
      margin-left: 6px;
    }
  }
}
.dialog-content {
  display: flex;
  justify-content: space-between;
  padding: 10px;
  & > div {
    padding: 12px;
    border: 1px solid var(--el-border-color-light);
    border-radius: 6px;
    box-shadow: 0 0 12px #ddd;
  }
  .left {
    width: 62%;
    margin-right: 10px;
    .chart-type {
      display: flex;
      justify-content: center;
      margin-bottom: 10px;
    }
    .col-item {
      display: inline-flex;
      width: 50%;
    }
  }
  .right {
    width: 38%;
    #previewChart {
      position: relative;
      width: 100%;
      height: 100%;
      min-height: 300px;
    }
  }
}

:deep(.el-form-item--small) {
  width: 100%;
  margin-bottom: 10px;
}
:deep(.el-form-item--small > div) {
  width: 100%;
}
:deep(.el-divider__text) {
  font-weight: bold;
}
.dark .dialog-content > div {
  box-shadow: unset;
}
</style>
